using Consul;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Beauty.Net.Consul.Core;

/// <summary>
/// Consul服务发现实现
/// </summary>
public class ConsulDiscoveryService : IConsulDiscoveryService
{
    private readonly ILogger<ConsulDiscoveryService> _logger;
    private readonly ConsulOptions _options;
    private readonly IConsulClient _consulClient;
    private readonly Random _random = new();
    
    /// <summary>
    /// 构造函数
    /// </summary>
    public ConsulDiscoveryService(
        ILogger<ConsulDiscoveryService> logger,
        IOptions<ConsulOptions> options,
        IConsulClient consulClient)
    {
        _logger = logger;
        _options = options.Value;
        _consulClient = consulClient;
    }
    
    /// <summary>
    /// 获取所有服务实例
    /// </summary>
    public async Task<List<ServiceInstance>> GetAllServicesAsync(CancellationToken cancellationToken = default)
    {
        try
        {
            // 获取所有服务
            var services = await _consulClient.Agent.Services(cancellationToken);
            var result = new List<ServiceInstance>();
            
            foreach (var service in services.Response.Values)
            {
                // 获取服务健康状态
                var healthCheck = await _consulClient.Health.Checks(service.ID, cancellationToken);
                var isHealthy = healthCheck.Response.All(check => check.Status == HealthStatus.Passing);
                
                result.Add(new ServiceInstance
                {
                    ServiceId = service.ID,
                    ServiceName = service.Service,
                    Address = service.Address,
                    Port = service.Port,
                    Tags = service.Tags?.ToList() ?? new List<string>(),
                    IsHealthy = isHealthy
                });
            }
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取所有服务失败");
            throw;
        }
    }
    
    /// <summary>
    /// 根据服务名称获取服务实例
    /// </summary>
    public async Task<List<ServiceInstance>> GetServicesAsync(string serviceName, CancellationToken cancellationToken = default)
    {
        try
        {
            // 获取健康的服务实例
            var queryResult = await _consulClient.Health.Service(serviceName, null, true, cancellationToken);
            var result = new List<ServiceInstance>();
            
            foreach (var serviceEntry in queryResult.Response)
            {
                result.Add(new ServiceInstance
                {
                    ServiceId = serviceEntry.Service.ID,
                    ServiceName = serviceEntry.Service.Service,
                    Address = serviceEntry.Service.Address,
                    Port = serviceEntry.Service.Port,
                    Tags = serviceEntry.Service.Tags?.ToList() ?? new List<string>(),
                    IsHealthy = true
                });
            }
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取服务实例失败: {ServiceName}", serviceName);
            throw;
        }
    }
    
    /// <summary>
    /// 随机获取一个可用的服务实例
    /// </summary>
    public async Task<ServiceInstance?> GetRandomServiceAsync(string serviceName, CancellationToken cancellationToken = default)
    {
        var services = await GetServicesAsync(serviceName, cancellationToken);
        
        if (services.Count == 0)
        {
            _logger.LogWarning("未找到可用的服务实例: {ServiceName}", serviceName);
            return null;
        }
        
        // 随机选择一个服务实例
        var randomIndex = _random.Next(0, services.Count);
        return services[randomIndex];
    }
    
    /// <summary>
    /// 检查服务是否健康
    /// </summary>
    public async Task<bool> IsServiceHealthyAsync(string serviceId, CancellationToken cancellationToken = default)
    {
        try
        {
            var healthCheck = await _consulClient.Health.Checks(serviceId, cancellationToken);
            return healthCheck.Response.All(check => check.Status == HealthStatus.Passing);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "检查服务健康状态失败: {ServiceId}", serviceId);
            return false;
        }
    }
}